package org.brisling.medical.queryService;

import java.util.ArrayList;
import java.util.Arrays;
import java.util.LinkedHashMap;
import java.util.List;
import java.util.Map;

import javax.persistence.EntityManager;
import javax.persistence.PersistenceContext;

import org.brisling.authorize.shiro.ShiroSecurityService;
import org.brisling.base.domain.ListDomain;
import org.brisling.base.service.AbstractBaseQueryService;
import org.brisling.common.ConstSysParam;
import org.brisling.common.SysConfig;
import org.brisling.common.exception.DangerousOperatorException;
import org.brisling.common.util.DateUtil;
import org.brisling.common.util.LongUtil;
import org.brisling.common.util.StringUtil;
import org.brisling.medical.domain.MedicalDrugCounting;
import org.brisling.medical.domain.MedicalDrugPercent;
import org.brisling.sysman.queryService.QueryDictionaryService;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.RestController;
import org.springframework.web.servlet.ModelAndView;

/**
 * 
 * <p>Title: QueryMedicalDrugCountingService</p>
 * <p>Description: 大额住院费用监控查询service</p>
 * <p>Company: tongking</p>
 * @author shura
 * @since 1.0
 * @version 1.0
 * @date 2016年7月20日 下午10:06:38
 */
@RestController
@RequestMapping("/drugCounting/query")
public class QueryMedicalDrugCountingService extends AbstractBaseQueryService<MedicalDrugCounting>{
	
	@Autowired
	private QueryDictionaryService dicService;
	
	@Autowired
	private ShiroSecurityService shiroSecurityService;
	
	public QueryMedicalDrugCountingService(){
		this.moduleName = ConstSysParam.MODULE_MEDICAL_DRUG_COUNTING;
		this.subSystem = ConstSysParam.SUBSYSTEM_MEDICAL;
		this.tableName = this.moduleName;
		this.clazz = MedicalDrugCounting.class;
		typeMap = this.getTypeMap(clazz);
	}
	
	@PersistenceContext(unitName=ConstSysParam.SUBSYSTEM_SYSMAN)
	@Autowired
	protected void setEntityManager(EntityManager entityManager){
		this.entityManager = entityManager;		
	}
	
	@RequestMapping("/mainPage.action")
	public ModelAndView getMainPage(){
		return this.getBizMainPage();
	}
	
	/* (non-Javadoc)
	 * @see org.brisling.service.sysman.DepartmentServiceInf#getEditPage()
	 */
	@RequestMapping("/editPage.action")
	public ModelAndView getEditPage(){
		return this.getBizEditPage();
	}
	
	@RequestMapping("/getListDomain.action")
	public ListDomain<MedicalDrugCounting> getListDomain(@RequestParam(value="page",required=false) Integer page,
			@RequestParam(value="rows",required=false) Integer rows,
			@RequestParam(value="condition",required=false) String condition,
			@RequestParam(value="sort",required=false) String sort){		
		
		StringBuilder sb = new StringBuilder();
		String sql = "";
		if(condition!=null){
			String whereCorse=String.format(sb.append("deptid = %1$s").toString(),condition);
			sql = String.format(this.TW_SQL, this.tableName,whereCorse);
		}else{
			sql = String.format(this.T_SQL, this.tableName);
		}
		
		return super.getPagedListDomain(page,rows,sql);
	}
	@RequestMapping("/popPage.action")
	public ListDomain<MedicalDrugCounting> popPage(@RequestBody(required=false) String body){		
		String sql = "select * from medical_drug_counting c";
		Map<String,Object> map = this.getBodyParam(body);
		if(map.containsKey("groupBy")){
			String group = (String) map.get("groupBy");
			if(group.equals("doct")){
				sql = "select doct_code, doct_name, sum(drug_sum) drug_sum, sum(drug_price) drug_price, sum(total_price) total_price from medical_drug_counting c where %1$s and is_drug != 0 group by doct_code, doct_name";
			}
			else if(group.equals("dept")){
				sql = "select dept_code, dept_name, sum(drug_sum) drug_sum, sum(drug_price) drug_price, sum(total_price) total_price from medical_drug_counting c where %1$s and is_drug != 0 group by dept_code, dept_name";
			}
			else if(group.equals("drug")){
				sql = "select drug_code, drug_name, sum(drug_sum) drug_sum, sum(drug_price) drug_price, sum(total_price) total_price from medical_drug_counting c where %1$s and is_drug != 0 group by drug_code, drug_name";
			}
			else if(group.equals("anti")){
				sql = "select drug_code, drug_name, sum(drug_sum) drug_sum, sum(drug_price) drug_price, sum(total_price) total_price from medical_drug_counting c where isantisepsis = 1 and %1$s and is_drug != 0 group by drug_code, drug_name";
			}
			else if(group.equals("from")){
				sql = "select drug_code, drug_name, sum(drug_sum) drug_sum, '是' drug_from from medical_drug_counting c where %1$s and is_drug != 0 group by drug_code, drug_name";
			}
			else if(group.equals("allDrug")){
				sql = "SELECT drug_num, drug_price, drug_sum, drug_anti FROM (SELECT SUM (drug_sum) drug_num, SUM (drug_price) drug_price, COUNT (DISTINCT (drug_code)) drug_sum, '1' anti FROM medical_drug_counting c where %1$s) aall LEFT JOIN (SELECT COUNT (DISTINCT (drug_code)) drug_anti, '1' anti FROM medical_drug_counting cd WHERE %1$s AND CD.ISANTISEPSIS = 1) ant ON ant.anti = aall.anti";
			}
		}
		LinkedHashMap<String,String> orderMapOrd = new LinkedHashMap<>();
		if(map.containsKey("orderBy")){
			String order = (String) map.get("orderBy");
			if(sql == null || sql.trim().length() < 1){
				return new ListDomain<>();
			}
			if(order.equals("number")){
				orderMapOrd.put("drug_sum", "desc");
			}
			else if(order.equals("price")){
				orderMapOrd.put("drug_price", "desc");
			}
			else if(order.equals("priPer")){
				orderMapOrd.put("drug_price", "desc");
			}
		}
		return super.getListDomainByConditionAndOrder(sql, map, typeMap, orderMapOrd, true);
		
		
	}
	
	/**
	 * 获取药品使用统计信息
	 * @param body
	 * @return
	 */
	@RequestMapping("/getDrugCount.action")
	public List<MedicalDrugCounting> getDrugCount(@RequestBody(required=false) String body){
		
		String sqlCode = "query_durg_counting";
		String sql = dicService.getSqlByBizcode(sqlCode);
		
		List<MedicalDrugCounting> lists = new ArrayList<MedicalDrugCounting>();
		
		Map<String,Object> _param = this.getBodyParam(body);
		
		if(_param != null && _param.containsKey(ConstSysParam.CONDITION_MAP_KEY)){
			Map<String,Object> _vMap = (Map<String, Object>) _param.get(ConstSysParam.CONDITION_MAP_KEY);
			
			//判断参数有效性
			if(_vMap!=null){
				
				//判断必须的参数是否具备
				if(_vMap.containsKey("start_time")&&_vMap.containsKey("end_time")&& _vMap.containsKey("order")){
					
					//溶媒排除参数
					String excludeCode = SysConfig.getConfig(ConstSysParam.MENSTRUUMCODE);
					if(null !=excludeCode){
						_vMap.put(ConstSysParam.MENSTRUUMCODE, excludeCode);
					}
					sql = StringUtil.formatSql(sql, _vMap);
					
					lists = super.getAllList(sql);
				}
			}
		}
		
		return lists;
	}
	
	/**
	 * 获取药占比统计信息
	 * @param body
	 * @return
	 */
	@RequestMapping("/getDrugPercent.action")
	public List<MedicalDrugPercent> getDrugPercent(@RequestBody(required=false) String body){
		
		//门诊科室医生药占比
		String sqlCode_outpatient_deptdoct = "drug_percent_outpatient_deptdoct";
		
		//住院药占比
		String sqlCode_inpatient_deptdoct = "drug_percent_inpatient_deptdoct";
		
		List<MedicalDrugPercent> lists = new ArrayList<MedicalDrugPercent>();
		
		Map<String,Object> _param = this.getBodyParam(body);
		
		if(_param != null && _param.containsKey(ConstSysParam.CONDITION_MAP_KEY)){
			Map<String,Object> _vMap = (Map<String, Object>) _param.get(ConstSysParam.CONDITION_MAP_KEY);
			//增加部门、人员参数设定
			String userid = shiroSecurityService.getCurrentUserIdentify();
			if(!this.isSuperDept(userid,ConstSysParam.QUERY_ALL, "query_medical_all")){
				if(isManageJob(userid)){
					//查找科室数据	
					String deptids = this.getJobDeptidAndAccountDeptids(userid);
					_vMap.put("dept_code", deptids);					
				}else{
					//查找医生数据	
					_vMap.put("doct_code", userid);					
				}		
			}
			//判断参数有效性
			if(_vMap!=null){
				
				//判断必须的参数是否具备
				if(_vMap.containsKey("start_time")&&_vMap.containsKey("end_time") && _vMap.containsKey("count_type")){					
					
					
					String field = null;
					if(_vMap.containsKey("layer")){
						
						Object obj = _vMap.get("layer").toString();
						if(obj!=null){
							field = obj.toString();							
						}						
					}
					
					
					//判断是否查询所有业务
					String _type = "all";
					if(_vMap.containsKey("type") && _vMap.containsKey("layer")){
						
						String _layer = null;
						Object obj = _vMap.get("layer");
						if(obj!=null){
							_layer = obj.toString();
							//判断是否在患者层
							if(_layer!=null && _layer.compareTo("patient")==0){
								//获取数据分类（门诊、住院）
								Object obj1 = _vMap.get("type");
								if(obj1!=null){
									_type = obj1.toString();
								}								
							}
						}
					}
					
					List<MedicalDrugPercent> olists = null;
					List<MedicalDrugPercent> ilists = null;
					
					if(_type.compareTo("all")==0 || _type.compareTo("out")==0){
						String sqlin = dicService.getSqlByBizcode(sqlCode_outpatient_deptdoct);
						sqlin = StringUtil.formatSql(sqlin, _vMap);						
	
						try {
							olists = super.getClassedAllList(sqlin, MedicalDrugPercent.class);
						} catch (DangerousOperatorException e) {
							// TODO Auto-generated catch block
							e.printStackTrace();
						}
					}
					
					if(_type.compareTo("all")==0 || _type.compareTo("in")==0){
						String sqlout = dicService.getSqlByBizcode(sqlCode_inpatient_deptdoct);
						sqlout = StringUtil.formatSql(sqlout, _vMap);					
						
						try {
							ilists = super.getClassedAllList(sqlout, MedicalDrugPercent.class);
						} catch (DangerousOperatorException e) {
							// TODO Auto-generated catch block
							e.printStackTrace();
						}
					}
					switch(_type){
						case "all":
							lists = this.combinList(olists, ilists, field);
							break;
						case "in":
							lists = ilists;
							break;
						case "out":
							lists = olists;
							break;
						
						default:
							lists = this.combinList(olists, ilists, field);
					}
					
				}
			}
		}
		
		return lists;
	}
	
	/**
	 * 合并统计值
	 * @param outpatientLists	门诊药占比信息
	 * @param inpatientLists	住院药占比信息
	 * @param field				合并关联字段
	 * @return
	 */
	private List<MedicalDrugPercent> combinList(List<MedicalDrugPercent> outpatientLists,List<MedicalDrugPercent> inpatientLists,String field){
		
		if(outpatientLists==null || outpatientLists.size()<=0){
			
			return inpatientLists;
		}
		
		if(inpatientLists==null || inpatientLists.size()<=0){
			
			return outpatientLists;
		}
		Map<Long,MedicalDrugPercent> maps = new LinkedHashMap<Long,MedicalDrugPercent>();
		//缓存住院信息
		for(MedicalDrugPercent domain:inpatientLists){			
			Long _id = null;
			if(field!=null){
				switch(field){
				case "dept":
					_id = domain.getDept_id();
					break;
				case "doct":
					_id = domain.getDoct_id();
				}
			}
			if(_id!=null){
				maps.put(_id, domain);
			}			
		}
		
		for(MedicalDrugPercent domain:outpatientLists){
			Long _id = null;
			if(domain!=null){
				switch(field){
				case "dept":
					_id = domain.getDept_id();
					break;
				case "doct":
					_id = domain.getDoct_id();
				}
				
				if(_id!=null){
					
					MedicalDrugPercent inM = null;
					if(!maps.containsKey(_id)){
						//缓存中没有数据，添加到缓存中
						domain.setDrug_count(domain.getOut_drug_count());
						domain.setPrice_count(domain.getOut_price_count());
						domain.setDrug_percent(domain.getOut_drug_percent());
						maps.put(_id, domain);
					}else{
						//缓存中有数据，直接copy
						inM = maps.get(_id);
						
						inM.setOut_drug_count(domain.getOut_drug_count());
						inM.setOut_patient_num(domain.getOut_patient_num());
						inM.setOut_price_count(domain.getOut_price_count());
						inM.setOut_drug_percent(domain.getOut_drug_percent());					
					}
								
				}
			}
		}
		List<MedicalDrugPercent> retList = new ArrayList<MedicalDrugPercent>();
		for(MedicalDrugPercent m:maps.values()){
			//计算药品收人
			Double odc = m.getOut_drug_count()==null?0:m.getOut_drug_count();
			Double idc = m.getIn_drug_count()==null?0:m.getIn_drug_count();
			
			m.setDrug_count(odc+idc);
			
			//计算总收人
			Double opc = m.getOut_price_count()==null?0:m.getOut_price_count();
			Double ipc = m.getIn_price_count()==null?0:m.getIn_price_count();
			m.setPrice_count(opc+ipc);
			
			//计算药占比
			Double opp = 0d;
			if((odc+idc)>0 && (opc+ipc)>0){
				opp = (odc+idc)/(opc+ipc);
			}
			m.setDrug_percent(opp);
			retList.add(m);
		}		
		return retList;
	}
//	@RequestMapping("/popPage.action")
//	public ListDomain<MedicalDrugCounting> popPageDoct(@RequestParam(value="page",required=false) Integer page,
//			@RequestParam(value="rows",required=false) Integer rows,
//			@RequestParam(value="condition",required=false) String condition,
//			@RequestParam(value="sort",required=false) String sort){		
//		
//		StringBuilder sb = new StringBuilder();
//		String sql = "select * from medical_drug_counting";
//		if(condition!=null){
//			String whereCorse=String.format(sb.append("deptid = %1$s").toString(),condition);
//			sql = String.format(this.TW_SQL, this.tableName,whereCorse);
//		}else{
//			sql = String.format(this.T_SQL, this.tableName);
//		}
//		return super.getPagedListDomain(page,rows,sql);
//	}
	@RequestMapping("/popPageDrug.action")
	public ModelAndView getPopPageDrug(){
		String _page = "PopMainDrug";
		return new ModelAndView("/medical/medical_drug_counting/"+_page);
	}
	@RequestMapping("/popPageDept.action")
	public ModelAndView getPopPageDept(){
		String _page = "PopMainDept";
		return new ModelAndView("/medical/medical_drug_counting/"+_page);
	}
	@RequestMapping("/popPageDoct.action")
	public ModelAndView getPopPageDoct(){
		String _page = "PopMainDoct";
		return new ModelAndView("/medical/medical_drug_counting/"+_page);
	}
	@RequestMapping("/popPageFrom.action")
	public ModelAndView getPopPageFrom(){
		String _page = "PopMainDrugFrom";
		return new ModelAndView("/medical/medical_drug_counting/"+_page);
	}
	@RequestMapping("/popPageAnti.action")
	public ModelAndView getPopPageAnti(){
		String _page = "PopMainDrugAnti";
		return new ModelAndView("/medical/medical_drug_counting/"+_page);
	}
	
	@RequestMapping("/popPageDrugPercent.action")
	public ModelAndView getPopPageDrugPercent(){
		String _page = "PopMainDrugPercent";
		return new ModelAndView("/medical/medical_drug_counting/"+_page);
	}
	
	@RequestMapping("/getList.action")
	public List<MedicalDrugCounting> getList(@RequestParam(value="page",required=false) Integer page,
			@RequestParam(value="rows",required=false) Integer rows,
			@RequestParam(value="deptid",required=false) Integer deptid,
			@RequestParam(value="sort",required=false) String sort){		
		
		StringBuilder sb = new StringBuilder();
		String sql = "";
		if(deptid!=null){
			String whereCorse=String.format(sb.append("\"deptid\" = %1$d").toString(),deptid);
			sql = String.format(this.TW_SQL, this.tableName,whereCorse);
		}else{
			sql = String.format(this.T_SQL, this.tableName);
		}
		
		return super.getPagedList(page,rows,sql);
	}

	public List<MedicalDrugCounting> getList(String monitor_year_month){
		
		String sql = String.format("select * from %1$s where monitor_year_month='%2$s'",this.tableName,monitor_year_month); 
		//查询表
		return super.getAllList(sql);
		
	}
	/**
	 * 根据用户id查找用户信息
	 * @param id	用户id
	 * @return 用户信息记录 
	 */
	@RequestMapping("/getOne.action")
	public MedicalDrugCounting getOne(@RequestParam(value="id",required=false) Long id){
		return super.getOne(id);
	}
	
	/**
	 * 根据用户唯一编码查找用户信息
	 * @param identify	用户唯一编码
	 * @return 用户信息记录
	 */
	@RequestMapping("/getOneByIdentify.action")
	public MedicalDrugCounting getOneByIdentify(@RequestParam(value="identify",required=false) String identify){	
		return super.getOneByIdentify(identify);
	}

	/**
	 * 执行自动统计
	 * @return 
	 */
	public List<MedicalDrugCounting> autoMonitor(Integer year,Integer month){
		String[] yestodayMonth = null;
		if(year ==null || month ==null)
			yestodayMonth = DateUtil.getYestodayMonthDay();
		else{
			yestodayMonth = DateUtil.getMonthDay(year, month);
		}
		List<MedicalDrugCounting> newLists = countDrugCounting(yestodayMonth[2],yestodayMonth[0],yestodayMonth[1]);
		
		//查询已有数据
		List<MedicalDrugCounting> oldLists = this.getList(yestodayMonth[2]);
		LinkedHashMap<String,MedicalDrugCounting> lmap = new LinkedHashMap<String,MedicalDrugCounting>();
		
		//将已有值存入临时map
		if(oldLists!=null && oldLists.size()>0){
			
			for(int i=0;i<oldLists.size();i++){
				MedicalDrugCounting b = oldLists.get(i);
				String _key = null;
				if(b.getDept_code() == null){
					continue;
				}
				if(b.getDoct_code()==null ){
					_key = b.getDrug_code() + "-" + b.getDept_code().toString();
				}else{
					_key = b.getDrug_code() + "-" + b.getDept_code() +"-" + b.getDoct_code();
				}
				lmap.put(_key, b);
			}
		}
		
		
		if(newLists!=null){
			if(lmap!=null && lmap.size()>0){
				for(int i=0;i<newLists.size();i++){
					MedicalDrugCounting b = newLists.get(i);
					if(b.getDept_code() == null || b.getPatient_type() == null){
						continue;
					}
					String _key = null;
					if(b.getDoct_code()==null ){
						_key = b.getDrug_code() + "-" + b.getDept_code().toString();
					}else{
						_key = b.getDrug_code() + "-" + b.getDept_code() +"-" + b.getDoct_code();
					}
					if(lmap.containsKey(_key)){
						newLists.get(i).setId(lmap.get(_key).getId());
					}
					System.out.println(i);
				}
			}
			
			return newLists;			
		}
		return newLists;	
	}

	private List<MedicalDrugCounting> countDrugCounting(String year_month,String startDate ,String endDate) {
		// TODO Auto-generated method stub
		//出院病人
		String _count_type = "0";
		
		//住院药品统计语句
		String[] sqlins= {"medical_drug_counting_doct_inpatient"};
		
		//门诊药品统计语句
		String[] sqlouts= {"medical_drug_counting_doct_outpatient"};
		
		//统计全院数据-住院

		List<String> inSqls = new ArrayList<String>();
		List<String> outSqls = new ArrayList<String>();
		for(int i = 0;i<sqlins.length;i++){
			String sql = dicService.getSqlByBizcode(sqlins[i]);
			if(sql!=null){
				inSqls.add(sql);
			}
		}
		for(int i = 0;i<sqlouts.length;i++){
			String sql = dicService.getSqlByBizcode(sqlouts[i]);
			if(sql!=null){
				outSqls.add(sql);
			}
		}
		//所有数据
		List<MedicalDrugCounting> inLists = super.monitorCountBase(year_month,startDate,endDate,inSqls);
		List<MedicalDrugCounting> outLists = super.monitorCountBase(year_month,startDate,endDate,outSqls);	
		LinkedHashMap<String, MedicalDrugCounting> inpatientList = new LinkedHashMap<>();
		for(MedicalDrugCounting e:inLists){
			String _key = "";
			if(e.getDoct_code() == null){
				_key = e.getDrug_code() + "-" + "NULL" + "-" + e.getDept_code();
			}
			else{
				_key = e.getDrug_code() + "-" + e.getDoct_code() + "-" + e.getDept_code();
			}
			inpatientList.put(_key, e);
		}
		for(MedicalDrugCounting e:outLists){
			String _key = "";
			if(e.getDoct_code() == null){
				_key = e.getDrug_code() + "-" + "NULL" + "-" + e.getDept_code();
			}
			else{
				_key = e.getDrug_code() + "-" + e.getDoct_code() + "-" + e.getDept_code();
			}
			if(inpatientList.containsKey(_key)){
				e.setDrug_price(e.getDrug_price() + inpatientList.get(_key).getInp_drug_price());
				e.setDrug_sum(e.getDrug_sum() + inpatientList.get(_key).getInp_drug_sum());
				e.setTotal_price(e.getTotal_price() + inpatientList.get(_key).getTotal_price());
				if(e.getTotal_price() != null && e.getDrug_price() != null){
					if(e.getTotal_price() > 0 && e.getDrug_price() > 0){
						e.setMedical_per(e.getDrug_price() / e.getTotal_price());
					}
				}
				e.setInp_drug_price(inpatientList.get(_key).getInp_drug_price());
				e.setInp_drug_sum(inpatientList.get(_key).getInp_drug_sum());
				inpatientList.remove(_key);
			}
		}
		if(!inpatientList.isEmpty()){
			for(String s:inpatientList.keySet()){
				MedicalDrugCounting e = inpatientList.get(s);
				e.setDrug_price(e.getInp_drug_price());
				e.setOutp_drug_price(0D);
				e.setDrug_sum(e.getInp_drug_sum());
				e.setOutp_drug_sum(0L);
				if(e.getTotal_price() != null && e.getInp_drug_price() != null){
					if(e.getTotal_price() > 0 && e.getInp_drug_price() > 0){
						e.setMedical_per(e.getInp_drug_price() / e.getTotal_price());
					}
				}
				if(e.getIs_drug().equals("0")){
					e.setIsantisepsis("0");
					e.setIsbasedrug("0");
				}
				outLists.add(e);
			}
		}
		return outLists;
	}
}
